package labeler;

import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import org.junit.Test;

public class LabeledCollectionTest {

	@Test
	public void getValuesFor_OneLabel() {
		LabeledCollection<String, String> collection = new LabeledCollection<String, String>();
		collection.add("hello", "greeting");
		Set<String> labeled = collection.getValuesFor("greeting");
		
		assertTrue(labeled.contains("hello"));
	}
	
	@Test
	public void getValuesFor_NothingAdded() {
		LabeledCollection<String, String> collection = new LabeledCollection<String, String>();
		Set<String> labeled = collection.getValuesFor("hello");
		
		assertEquals(0, labeled.size());
	}

	@Test
	public void getValuesFor_MultipleLabelsAndValues() {
		LabeledCollection<String, String> collection = new LabeledCollection<String, String>();
		String label1 = "label1";
		String label2 = "label2";
		String label3 = "label3";
		String value1 = "value1";
		String value2 = "value2";
		
		collection.add(value1, label1, label2);
		collection.add(value2, label2, label3);
		
		Set<String> labeled1 = collection.getValuesFor(label1);
		assertSetContainsOnly(labeled1, value1);
		
		Set<String> labeled2 = collection.getValuesFor(label2);
		assertSetContainsOnly(labeled2, value1, value2);
		
		Set<String> labeled3 = collection.getValuesFor(label3);
		assertSetContainsOnly(labeled3, value2);
	}
	
	@Test
	public void getValuesFor_ReturnsCopyOfSet() {
		LabeledCollection<String, String> collection = new LabeledCollection<String, String>();
		String label = "label";
		collection.add("val", label);
		
		Set<String> labeled1 = collection.getValuesFor(label);
		labeled1.add("bogus");
		Set<String> labeled2 = collection.getValuesFor(label);

		assertNotEquals(labeled1, labeled2);
	}
	
	@Test
	public void getLabelsFor_WithOneValue() {
		LabeledCollection<String, String> collection = new LabeledCollection<String, String>();
		String label = "label";
		String value = "value";
		
		collection.add(value, label);
		
		Set<String> labels = collection.getLabelsFor(value);
		assertSetContainsOnly(labels, label);
	}
	
	@Test
	public void getLabelsFor_WithNothing() {
		LabeledCollection<String, String> collection = new LabeledCollection<String, String>();
		
		Set<String> labels = collection.getLabelsFor("value");
		assertSetContainsOnly(labels);
	}
	
	@Test
	public void getLabelsFor_ReturnsCopy() {
		LabeledCollection<String, String> collection = new LabeledCollection<>();
		String value = "value";
		collection.add(value, "label1");

		Set<String> labels1 = collection.getLabelsFor(value);
		labels1.add("bogus");
		Set<String> labels2 = collection.getLabelsFor(value);

		assertNotEquals(labels1, labels2);
	}
	
	@SafeVarargs
	private static <T> void assertSetContainsOnly(Set<T> set, T... items) {
		assertEquals(new HashSet<T>(Arrays.asList(items)), set);
	}
}
